/*
   Copyright 2009 Bloo. All Rights Reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package org.youtensils.www.client.data;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;

/**
 * Provides a JSONP capabilities by wrapping around a native JavaScript implementation.
 * @author Bobby Soares
 */
public abstract class JsonLoader {
	protected static int RequestIdCounter = 0;
	/**
	 * Handles the JSON response to a JSONP request.
	 * @param jso the JSON object returned from the JSONP request
	 */
	public void handleJsonResponse(JavaScriptObject jso) { }
	/**
	 * Initiates a JSONP request to a given URL with a given handler.
	 * @param url the URL to be requested
	 * @param handler the JSON response handler
	 */
	protected void getJson(String url, JsonLoader handler){
		getJson(RequestIdCounter++, url, handler);
	}
	/**
	 * @param requestId
	 * @param url
	 * @param handler
	 */
	/**
	 * Begins a JSONP request by adding a script reference to the document head.
	 * @param requestId an id identifying the request
	 * @param url the URL for the JSONP request
	 * @param handler the JSON response handler
	 */
	protected native static void getJson(int requestId, String url, JsonLoader handler) /*-{
	    var callback = "callback" + requestId;
	    var lastObj;
	    var script = document.createElement("script");
	    script.setAttribute("src", url+callback);
	    script.setAttribute("type", "text/javascript");
	
	    window[callback] = function(jsonObj) {
	    	try{
	    		lastObj = jsonObj;
		    	handler.@org.youtensils.www.client.data.JsonLoader::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(jsonObj);
		    	window[callback + "done"] = true;
	    	}catch(x){}
	    }
	    
	    // JSON download has 10-second timeout
	    setTimeout(function() {
	    	try{
		    	if (!window[callback + "done"]) {
		    		handler.@org.youtensils.www.client.data.JsonLoader::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(null);
		    	} 
		
		    	// cleanup
		    	document.body.removeChild(script);
		    	delete window[callback];
		    	delete window[callback + "done"];
	    	}catch(x){}
	    }, 10000);
	    
	    document.body.appendChild(script);
	}-*/;
  /**
   * Extracts a numeric value from a JavaScript given an Object array defining the attribute path.
   * @param obj the JavaScript object from which the numeric value should be extracted
   * @param path the path to the attribute which should be extracted
   * @return the numeric value of the target attribute
   */
  public static double getNumericAttribute(JSONObject obj, Object[] path){
    try{
      String val = getStringAttribute(obj, path);
      return Double.valueOf(val);
    }catch(Exception x){}
    return 0;
  }
  /**
   * Extracts a string value from a JavaScript given an Object array defining the attribute path.
   * @param obj the JavaScript object from which the string value should be extracted
   * @param path the path to the attribute which should be exctracted
   * @return the string value of the target attribute
   */
  public static String getStringAttribute(JSONObject obj, Object[] path){
    try{
      JSONValue curObj = obj;
      for(int i=0; i<path.length; i++){
        Object pc = path[i];
        if(curObj == null) return "";
        if(pc.getClass() == String.class){
          JSONObject job = curObj.isObject();
          if(job == null) return "";
          curObj = job.get((String)pc);
        }else if(pc.getClass() == Integer.class){
          JSONArray jar = curObj.isArray();
          if(jar == null) return "";
          curObj = jar.get((Integer)pc);
        }else{
          return "";
        }
      }
      JSONString val = curObj.isString();
      if (val == null) {
        return curObj.toString();
      } else {
    	return val.stringValue();
      }
    }catch(Exception x){}
    return "";
  }
}
